﻿Imports System.Activities
Imports System.ComponentModel
Imports Microsoft.VisualBasic.Activities
Imports System.Threading.Tasks
Imports System.Activities.Presentation.Metadata
Imports System.Drawing

''' <summary>
''' Async execute activity
''' </summary>
''' <remarks>
''' http://geekswithblogs.net/DavidPaquette/archive/2010/10/26/wf4-asynchronous-workflows.aspx
''' </remarks>
Public Class AsyncTaskActivity
    Inherits AsyncCodeActivity
    Implements IRegisterMetadata

    <Browsable(False)>
    Public Property Body As New ActivityAction

    Protected Overrides Function BeginExecute(context As System.Activities.AsyncCodeActivityContext, callback As System.AsyncCallback, state As Object) As System.IAsyncResult
        Dim act = Me.CreateDynamicActivity(context)
        Dim inpArgAndVal = Me.GetArgumentsAndVariables(context)

        Dim asyncTask = task.Factory.StartNew(Function(ignore)
                                                  Return WorkflowInvoker.Invoke(act, inpArgAndVal)
                                              End Function, state)

        asyncTask.ContinueWith(Sub(t)
                                   callback(t)
                               End Sub)

        Return asyncTask
    End Function

    Protected Overrides Sub EndExecute(context As System.Activities.AsyncCodeActivityContext, result As System.IAsyncResult)

    End Sub

    Private Function GetArgumentsAndVariables(ByVal context As AsyncCodeActivityContext) As IDictionary(Of String, Object)
        Dim result As New Dictionary(Of String, Object)

        For Each wfProp As PropertyDescriptor In context.DataContext.GetProperties
            result.Add(wfProp.Name, wfProp.GetValue(context.DataContext))
        Next
        Return result
    End Function

    Private Function CreateDynamicActivity(ByVal context As AsyncCodeActivityContext) As Activity
        Dim result As New DynamicActivity
        For Each wfProp As PropertyDescriptor In context.DataContext.GetProperties
            Dim dynActProperty As New DynamicActivityProperty With {
                .Name = wfProp.Name,
                .Type = GetType(InArgument(Of )).MakeGenericType(wfProp.PropertyType)
            }
            dynActProperty.Value = Activator.CreateInstance(dynActProperty.Type)
            result.Properties.Add(dynActProperty)
        Next

        VisualBasic.SetSettings(result, VisualBasic.GetSettings(Me))
        result.Implementation = Function() (Body.Handler)
        Return result
    End Function

#Region "メタデータ"

    Public Sub Register() Implements System.Activities.Presentation.Metadata.IRegisterMetadata.Register
        Dim metadata As New Core.Presentation.DesignerMetadata
        metadata.Register()

        Dim builder As New AttributeTableBuilder
        builder.AddCustomAttributes(GetType(AsyncTaskActivity),
                            New DesignerAttribute(GetType(AsyncTaskActivityDesigner)) 
                            )
        MetadataStore.AddAttributeTable(builder.CreateTable)
    End Sub

#End Region

#Region "その他"

    ''' <summary>リソースより文字列の取得</summary>
    Private Shared Function GetResourceStrings(ByVal resourceName As String, ByVal defaultStrings As String)
        Dim locMes = CStr(Application.Current.TryFindResource(resourceName))
        If (locMes Is Nothing) OrElse (locMes.Trim = "") Then locMes = defaultStrings
        Return locMes
    End Function

#End Region

End Class
